home *** CD-ROM | disk | FTP | other *** search
- /* ps_package.c */
-
- #include "ps_package.h"
- #include "pspager.h"
- #include <string.h>
- #include <ctype.h>
- #ifdef AMIGA
- #include <utilities.h>
- #else
- #include "utilities.h"
- #endif
-
-
- /*--- private global data --------------------------------------------------------*/
-
- #define INBUF_SIZE 256*KB
- #define SYMBUF_SIZE 1*KB
- #define SYMTAB_SIZE 13
- #define PAGE_LIMIT 71
- #define IFSTK_SIZE 8
-
- #define CpyStr(s1,s2) { \
- if(s1 < s2) { \
- if(wrPtr+((s2)-(s1)) >= wrEnd) \
- FatalExit("input buffer overflow"); \
- strncpy(wrPtr,s1,s2-s1); \
- wrPtr += s2-s1; \
- } \
- }
-
- #define CpyChar(ch) { \
- if(wrPtr == wrEnd) \
- FatalExit("input buffer overflow"); \
- *wrPtr = (ch), wrPtr++; \
- }
-
- static char *inBuf,*wrPtr,*rdPtr;
- static char *symBuf,*symPtr,*symEnd,**symTab;
-
-
- /*--- private functions ---------------------------------------------------------*/
-
- static bool PSSymDefined(char *symName)
- {
- char *cp;
- int h = 0,d = 1;
-
- if(!symTab)
- return FALSE;
-
- for(cp=symName; *cp!='\0'; cp++)
- h = (256*h + *cp) % SYMTAB_SIZE;
- FOREVER
- if(symTab[h])
- if(strcmp(symTab[h],symName) == 0)
- return TRUE;
- else {
- h += d; d += 2; /* collision */
- if(h >= SYMTAB_SIZE)
- h -= SYMTAB_SIZE;
- if(d == SYMTAB_SIZE)
- FatalExit("symbol table overflow");
- }
- else
- return FALSE; /* empty slot */
- }
-
-
- /*--- public functions ----------------------------------------------------------*/
-
- /* PSPrintHdr
- ** ----------
- ** prints a PostScript 3.0 header to stdout, parameters are: name of file, file
- ** modification date or current date, number of pages, a string with PS font names
- ** and orientation specification.
- */
-
- void PSPrintHdr(char *fileName, time_t fileDate, int pages, char *fontNames,
- Orientation orient)
- {
- char dateStr[80],*userStr,*orientStr;
- int paTop,paLft,paHgt,paWdt,iaHgt,iaWdt;
-
- strftime(dateStr,80,"%H:%M Uhr %A, %d. %B %Y",localtime(&fileDate)); /*or %c*/
-
- if(!(userStr = getenv("USER")))
- userStr = "Nobody";
-
- if(orient == ePortrait) {
- orientStr = "Portrait";
- paTop = -31;
- paLft = -30;
- paHgt = 761;
- paWdt = 582;
- iaHgt = 730;
- iaWdt = 552;
- }
- else {
- orientStr = "Landscape";
- paTop = -28;
- paLft = -30;
- paHgt = 566;
- paWdt = 811;
- iaHgt = 538;
- iaWdt = 781;
- }
-
- printf("%%!PS-Adobe-3.0\n"
- "%%%%Title: (%s)\n"
- "%%%%Creator: (pspager: himself)\n"
- "%%%%CreationDate: (%s)\n"
- "%%%%For: (%s)\n"
- "%%%%Pages: %d\n"
- "%%%%DocumentFonts: %s\n"
- "%%%%DocumentNeededFonts: %s\n"
- "%%%%DocumentSuppliedFonts:\n"
- "%%%%DocumentData: Clean7Bit\n"
- "%%%%PageOrder: Ascend\n"
- "%%%%Orientation: %s\n"
- "%%ADO_PaperArea: %d %d %d %d\n"
- "%%ADO_ImageableArea: 0 0 %d %d\n"
- "%%EndComments\n"
- "/md 138 dict def md begin\n"
- "/currentpacking where {pop /sc_oldpacking currentpacking def true setpacking}if\n",
- fileName,dateStr,userStr,pages,fontNames,fontNames,orientStr,paTop,paLft,paHgt,
- paWdt,iaHgt,iaWdt);
- }
-
-
- /* PSPrintEnd
- ** ----------
- ** prints PostScript commands which terminate a document.
- */
-
- void PSPrintEnd(void)
- {
- printf("%%Trailer\nend\t\t%% md\n%%%%EOF\n");
- }
-
-
- /* PSInclFile
- ** ----------
- ** appends the contents of the specified file to stdout. The prefix PSPLIB_DIR is
- ** prepended to the file name. #include directives within the included file are
- ** recursively substituted (<> means PSP_LIBDIR, "" means current directory).
- ** #ifdef directives are evaluated considering symbol definitions made with
- ** PSDefSymbol(). #define directives cause further symbol definitions. Unsupported
- ** directives are: #undef, #elif.
- */
-
- void PSInclFile(char *fileName)
- {
- FILE *fp;
- char lnBuf[121],*lnPtr,*attr,ch;
- enum { eTokInclude, eTokDefine, eTokIfdef, eTokElse, eTokEndif, eTokIllegal } tok;
- static const char * const tokStrs[] = {
- "include", "define", "ifdef", "else", "endif", "illegal"
- };
- struct {
- enum { ePathIfdef, ePathElse } kind;
- bool taken;
- int ignCnt;
- } stk[IFSTK_SIZE];
- int idx = -1;
- bool taken,prtIt = TRUE;
-
- if(!(fp = fopen(fileName,"r"))) {
- printf("%%%%pspager error: could not include \"%s\"\n",fileName);
- return;
- }
- while(fgets(lnBuf,121,fp))
- if(lnBuf[0] == '#') {
- for(lnPtr=lnBuf+1; isalpha(*lnPtr); lnPtr++);
- *lnPtr = '\0', lnPtr++;
- for(tok=eTokInclude; tok<eTokIllegal; tok++)
- if(strcmp(lnBuf+1,tokStrs[tok]) == 0)
- break;
- while(*lnPtr==' ')
- lnPtr++;
- if(tok==eTokDefine || tok==eTokIfdef) {
- attr = lnPtr;
- while(isalnum(*lnPtr) || *lnPtr=='_')
- lnPtr++;
- *lnPtr = '\0';
- }
- switch(tok) {
- case eTokInclude:
- if(prtIt) {
- ch = *lnPtr=='<' ? '>' : '"', lnPtr++;
- attr = lnPtr;
- if(!(lnPtr = strchr(lnPtr,ch))) {
- puts("%%pspager error: invalid syntax");
- continue;
- }
- *lnPtr = '\0';
- if(ch == '>')
- attr = TackOn(PSP_LIBDIR,attr);
- PSInclFile(attr);
- }
- break;
- case eTokDefine:
- if(prtIt)
- PSDefSymbol(attr);
- break;
- case eTokIfdef:
- if(idx < 0 || stk[idx].taken) {
- idx++;
- if(idx == IFSTK_SIZE)
- FatalExit("#ifdef stack overflow");
- stk[idx].kind = ePathIfdef;
- stk[idx].taken = PSSymDefined(attr);
- stk[idx].ignCnt = 0;
- prtIt = stk[idx].taken;
- }
- else if(!stk[idx].taken)
- stk[idx].ignCnt++;
- break;
- case eTokElse:
- if(idx < 0) {
- puts("%%pspager error: else without ifdef");
- continue;
- }
- if(stk[idx].ignCnt > 0)
- continue;
- if(stk[idx].kind == ePathElse) {
- puts("%%pspager error: unbalanced else");
- continue;
- }
- stk[idx].kind = ePathElse;
- taken = stk[idx].taken;
- prtIt = stk[idx].taken = !taken;
- break;
- case eTokEndif:
- if(idx < 0) {
- puts("%%pspager error: unbalanced endif");
- continue;
- }
- if(stk[idx].ignCnt > 0)
- stk[idx].ignCnt--;
- else {
- idx--;
- if(idx < 0 || stk[idx].taken)
- prtIt = TRUE;
- }
- break;
- default:
- puts("%%pspager error: unrecognized token");
- }
- }
- else
- if(prtIt)
- printf("%s",lnBuf); /*puts() appends a NL*/
- fclose(fp);
- }
-
-
- /* PSDefSymbol
- ** -----------
- ** defines a preprocessor symbol for evaluation by PSInclFile().
- ** Multiple definitions are ignored.
- */
-
- void PSDefSymbol(char *symName)
- {
- char *cp;
- int h = 0,d = 1;
-
- if(!symBuf) {
- symBuf = NEW(char,SYMBUF_SIZE);
- symPtr = symBuf;
- symEnd = symBuf+SYMBUF_SIZE;
- symTab = NEW(char *,SYMTAB_SIZE);
- memset(symTab,0,SYMTAB_SIZE*sizeof(char *));
- }
-
- for(cp=symName; *cp!='\0'; cp++)
- h = (256*h + *cp) % SYMTAB_SIZE;
- FOREVER
- if(symTab[h])
- if(strcmp(symTab[h],symName) == 0)
- return; /* already defined */
- else {
- h += d; d += 2; /* collision */
- if(h >= SYMTAB_SIZE)
- h -= SYMTAB_SIZE;
- if(d == SYMTAB_SIZE)
- FatalExit("symbol table overflow");
- }
- else
- break; /* empty slot found */
-
- if(symPtr+strlen(symName) >= symEnd)
- FatalExit("symbol buffer overflow");
- symTab[h] = symPtr;
- strcpy(symPtr,symName);
- symPtr += strlen(symName)+1;
- }
-
-
- /* PSUndefAll
- ** ----------
- ** frees all buffers allocated by PSDefSymbol()
- */
-
- void PSUndefAll(void)
- {
- DELETE(symBuf);
- DELETE(symTab);
- }
-
-
- /* PSReadFile
- ** ----------
- ** reads the contents of the specified file into internal buffers and returns the
- ** resulting number of pages.
- */
-
- int PSReadFile(FILE *inFile)
- {
- char lnBuf[121],*lnPtr,*wrEnd,*fndPtr;
- int lnCnt = 0,pgCnt = 1;
-
- if(!(inBuf = NEW(char,INBUF_SIZE)))
- FatalExit("no memory for input buffer");
- wrEnd = inBuf+INBUF_SIZE;
- wrPtr = rdPtr = inBuf;
-
- while(fgets(lnBuf,121,inFile)) {
- if(lnBuf[0] == '\f') {
- pgCnt++, lnCnt=0; /* form feed -> new page */
- continue;
- }
- lnPtr = lnBuf;
- while((fndPtr = strpbrk(lnPtr,"()\\\n"))) {
- CpyStr(lnPtr,fndPtr);
- if(*fndPtr == '\n') {
- CpyChar('\0');
- break;
- }
- CpyChar('\\');
- CpyChar(*fndPtr);
- lnPtr = fndPtr+1;
- }
- lnCnt++;
- if(lnCnt == PAGE_LIMIT)
- pgCnt++, lnCnt=0;
- }
- return pgCnt;
- }
-
-
- /* PSFreeFile
- ** ----------
- ** frees the internal buffers allocated by PSReadFile().
- */
-
- void PSFreeFile(void)
- {
- DELETE(inBuf);
- }
-
-
- /* PSNextLine
- ** ----------
- ** returns a pointer to the next line of the file read by PSReadFile(). The '\n' has
- ** been stripped and to all (, ) and \ characters a \ has been preprended. If there
- ** are no more lines, NULL is returned.
- */
-
- char *PSNextLine(void)
- {
- char *p;
-
- if(rdPtr < wrPtr) {
- p = rdPtr;
- rdPtr += strlen(p)+1;
- return p;
- }
- else
- return NULL;
- }
-
-
- /* TackOn
- ** ------
- ** concatenates a path name and a file name to a full path name. The returned string
- ** is owned by the caller (so it has to be freed by him/her).
- */
-
- char *TackOn(const char *pn, const char *fn)
- {
- int n = strlen(pn);
- char *fpn;
-
- if (n == 0) {
- fpn = NEW(char, strlen(fn)+1);
- strcpy(fpn, fn);
- }
- else if(pn[n-1] == '/' || pn[n-1] == ':') {
- fpn = NEW(char, n+strlen(fn)+1);
- sprintf(fpn,"%s%s",pn,fn);
- }
- else {
- fpn = NEW(char, n+strlen(fn)+2);
- sprintf(fpn,"%s/%s",pn,fn);
- }
- return fpn;
- }
-